package ngat.oss.simulation;

import java.rmi.*;
import java.rmi.server.*;
import java.util.*;
import java.util.*;
import java.io.*;
import java.text.*;
import ngat.message.GUI_RCS.*;
import ngat.util.*;

/** A rather naff class that just loads some windows from a file.*/
public class WindowLoader extends UnicastRemoteObject implements AvailabilityModel {

    /** UTC timezone.*/
    public static final SimpleTimeZone UTC = new SimpleTimeZone(0, "UTC");
    
    /** File format.*/
    static  SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");

    /** Display format.*/
    static SimpleDateFormat ddf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /** The list of windows.*/
    private List windows;

    public WindowLoader() throws RemoteException {
	sdf.setTimeZone(UTC);
	ddf.setTimeZone(UTC);
	windows = new Vector();
    }

    public void loadWindows(File file) throws Exception {

	BufferedReader bin = new BufferedReader(new FileReader(file));
	
	String line = null;
	
	long t1 = 0L;
	long t2 = 0L;
	
	
	while ((line = bin.readLine()) != null) {
	    
	    // <t1> <t2> <info>...
	    
	    line = line.trim();
		
	    if (line.equals("") ||
		line.startsWith("#") ||
		line.startsWith("/") ||
		line.startsWith("*"))
		continue;
	    
	    StringTokenizer st = new StringTokenizer(line);
	    
	    if (st.countTokens() < 2)
		throw new IllegalArgumentException("WindowLoader: loadWindows(): Missing args: "+line);
	  	    
	    String st1 = st.nextToken();
	    
	    try {
		t1 = (sdf.parse(st1)).getTime(); 
	    } catch (ParseException px) {
		throw new IllegalArgumentException("WindowSchedule: load: Illegal start time: "+st1);
	    }
	    
	    String st2 = st.nextToken();
	    
	    try {
		t2 = (sdf.parse(st2)).getTime(); 
	    } catch (ParseException px) {
		throw new IllegalArgumentException("WindowSchedule: load: Illegal end time: "+st2);
	    }
		
	    //if (st.hasMoreTokens())
	    //info = st.nextToken();
	    
	    TimeWindow w = new TimeWindow(t1, t2);
		
	    windows.add(w);
	}

    }

    /** Returns true if the specified time is available for scheduled operations.
     * @param time when we want to check.
     */
    public boolean isAvailable(long time) throws RemoteException {
	
	Iterator it = windows.iterator();
	while (it.hasNext()) {
	    
	    TimeWindow w = (TimeWindow)it.next();
	    
	    if (w.start <= time && w.end >= time)
		return false;
	}
	
	// no windows, so pass.
	return true;
    }
    
    /** Returns true if the specified time interval is fully available for scheduled operations.
     * @param start the start of the period of interest.
     * @param end the end of the period of interest.
     */
    public boolean isAvailable(long start, long end) throws RemoteException {
	
	// all we care about is: Is there a Window In Force (WIF) at time
	// being more pernicketty, would like to know if any window overlaps
	// with the execution of this group if started at time.
    
	// Note: overlap = [max(t, ws), min(t+x, we)]
	
	Iterator it = windows.iterator();
	while (it.hasNext()) {
	    
	    TimeWindow w = (TimeWindow)it.next();
	    
	    // work out the overlap if any..
	    
	    System.err.println("WL: Call avail(s,e), working out overlap if any");
	    System.err.println("WL: Call avail(s,e), P.start = "+sdf.format(new Date(start)));
	    System.err.println("WL: Call avail(s,e), P.end   = "+sdf.format(new Date(end)));
	    System.err.println("WL: Call avail(s,e), w.start = "+sdf.format(new Date(w.start)));
	    System.err.println("WL: Call avail(s,e), w.end   = "+sdf.format(new Date(w.end)));
	    
	    long tos = Math.max(start, w.start);
	    long toe = Math.min(end, w.end);
	    
	    System.err.println("WL: Call avail(s,e), working out overlap if any...["+
			       sdf.format(new Date(tos))+", "+sdf.format(new Date(toe))+"]");
	    
	    // found an overlap
	    if (tos < toe)
		return false;
	    
	}
	
	return true;
	
    }
    
    /** Returns a list of times which are UNavailable for scheduled operations
     * between start and end - inclusive/overlapping.
     * @param start the start of the period of interest.
     * @param end the end of the period of interest.
     */
    public List getUnavailableTimes(long start, long end) throws RemoteException {
	
	return windows;

    }

}
